path = require 'path'
_ = require 'underscore'
moment = require 'moment'
request = require 'request'
express = require 'express'
program = require 'commander'
httpProxy = require 'http-proxy'
xssFilter = require 'x-xss-protection'

config = require './config'
db = require './mods/base/db'
currency=require './helpers/currency'

multer = require 'multer'
morgan = require 'morgan'
ex_router = express.Router()
favicon = require 'serve-favicon'
session = require 'express-session'
bodyParser = require 'body-parser'
cookieParser = require 'cookie-parser'
methodOverride = require 'method-override'
MongoStore = require('connect-mongo')(session)

do ->

  program.version('0.0.1')
  .option('-p, --port <n>', 'listen port', parseInt)
  .option('--log <n>', 'the log file')
  .option('-r, --restHost <n>', 'the rest host')
  .parse process.argv

###*
 * initAppSetting 初始化应用配置
 * @param  {[type]} app [description]
 * @return {[type]}     [description]
###
initAppSetting = (app) ->
  app.set 'view engine', 'jade'
  app.set 'trust proxy', true
  app.set 'views', "#{__dirname}/views"

  app.locals._ = _
  app.locals.staticPrefix = '/static'
  app.locals.moment = moment
  app.locals.currency = currency
  app.locals.ENV = app.get 'env'
  app.locals.restUrlBase = "http://#{config.getRestHost()}"

  app.enable 'view cache' if app.get('env') == 'test'
  app

###*
 * staticMiddleware 静态文件的处理
 * @param  {[type]} app [description]
 * @return {[type]}     [description]
###
staticMiddleware = (app) ->

  hour = 3600
  hour = 0 if config.env is 'development'
  maxAge = 24 * hour

  name = 'static'

  staticConfigs = [
    {
      mount : config.component.urlPrefix
      path : "#{__dirname}/public"
    }
  ]
  _.each staticConfigs, (staticConfig) ->
    handler = express[name] staticConfig.path
    now = moment()
    expires = moment().add(1, 'day').toString()
    expires = '' if config.env is 'development'
    app.use staticConfig.mount, (req, res, next) ->
      res.header 'Expires', expires
      res.header 'Cache-Control', "public, max-age=#{maxAge}, s-maxage=#{hour}"
      handler req, res, next

# 初始化路由配置
initRouter = (app) ->
  router = require './helpers/router'
  routes = require './routes'
  router.initRoutes app, routes
  app.use ex_router

###*
 * devMiddleware 开发环境中用到的middleware
 * @param  {[type]} app [description]
 * @return {[type]}     [description]
###
devMiddleware = (app) ->
  app.use morgan('dev')
  dev = require './helpers/dev'
  staticMount = '/static'
  staticPath = "#{__dirname}/public"
  app.use staticMount, dev.extConverter staticPath

  app.use staticMount, dev.stylusParser staticPath
  app.use staticMount, dev.coffeeParser staticPath

proxy = (restType)->
  proxyServer = httpProxy.createProxyServer()
  (req, res, next) ->
    # 请求主机
    req.headers.host = config.getRestHost()

    # rest请求
    target = "http://#{config.getRestHost()}"

    proxyServer.web req, res, {
      target : target
    }

###*
 * initServer 初始化server
 * @return {[type]} [description]
###
initServer = ->
  # 实例化express
  app = express()
  # 设置启动参数
  initAppSetting app

  # 防御xss攻击
  app.use xssFilter()
  app.use require './mods/common/prevent_inject_mid'
  # 解析地址栏-错误处理
  app.use (req, res, next) ->
    err = null
    try
      decodeURIComponent req.path
    catch e
      err = e
    if err
      return res.status(500).json({error: 'URI解析错误！[URIError: URI malformed]', status: 'failed'})
    return next()

  # rest请求
  app.use '/rest', proxy('rest')
  
  app.use require('connect-timeout') 30 * 1000

  if app.get('env') == 'development' 
    devMiddleware app
  else
    # app.use morgan('tiny')
    morgan.token 'date_now', () ->
      date = new Date()
      year = date.getFullYear()
      month = date.getMonth()+1
      day = date.getDate()
      hour = date.getHours()
      minute = date.getMinutes()
      second = date.getSeconds()
      ms = date.getMilliseconds()
      if month < 10
        month = '0' + month
      if day < 10
        day = '0' + day
      if hour < 10
        hour = '0' + hour
      if minute < 10
        minute = '0' + minute
      if second < 10
        second = '0' + second
      return ""+ year + '-' + month + '-' + day + ' ' + hour + ':' + minute + ':' + second

    app.use morgan(":remote-addr - :remote-user :date_now :method :url HTTP/:http-version :status :res[content-length]")
  
  #记录所有请求的日志
  staticMiddleware app

  app.use '/healthchecks', (req, res) ->
    res.send 'success'

  app.use favicon path.join __dirname, 'public/img/code2_16.ico'
  app.use methodOverride()
  app.use(bodyParser.json())
  app.use(bodyParser.urlencoded({ extended: true }))
  # app.use(multer())
  app.use cookieParser()

  app.use session({
    resave: false
    saveUninitialized: true
    secret: 'appcms123456'
    key: 'appcmssid'
    cookie: { maxAge : 1000 * 60 * 60 * 2, httpOnly : true}  #2小时
    store: new MongoStore({
      url: db.getDbUrl()
    })
  })

  # 设置跨域访问
  app.all '*',(req,res,next)->
    res.header("Access-Control-Allow-Origin", "*")
    res.header("Access-Control-Allow-Headers", "X-Requested-With")
    res.header("Access-Control-Allow-Methods","PUT,POST,GET,DELETE,OPTIONS")
    res.header('Access-Control-Allow-Headers', 'Content-Type')
    # res.header("X-Powered-By",' 3.2.1')
    # res.header("Content-Type", "application/json;charset=utf-8")
    next()

  initRouter app


  app.use require('./mods/common/error')

  port = program.port || 8091

  app.listen(port)

  console.info "http server listen on #{port}"

if config.env is 'development'
  initServer()
else
  d = require('domain').create()
  d.on 'error', (err) ->
    console.error err.stack
  d.run ->
    initServer()